package com.app.server;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;

import com.app.game.chat.Message;
import com.app.game.other.Credit;
import com.app.game.other.Player;
import com.app.head.Head;
import com.app.head.HeadsConst;
import com.app.head.impl.HeadGameOver;
import com.app.head.impl.HeadGameStarting;
import com.app.head.impl.HeadMessage;
import com.app.head.impl.HeadPlayer;
import com.app.head.impl.HeadPlayerList;
import com.app.head.impl.HeadReadyNotification;
import com.app.head.impl.HeadResult;
import com.app.head.impl.HeadRoundDone;
import com.app.lan.Receiver;
import com.app.lan.Sender;
import com.app.observers.ClientObserver;
import com.app.observers.ClientSubject;
import com.app.task.Task;
import java.io.*;

public class ClientHandler extends Task implements ClientSubject{

	private Socket socket;
	private ObjectInputStream input;
	private ObjectOutputStream output;
	
	private Receiver<Head> headReceiver;
	//private Receiver<Player> playerReceiver;
	//private Receiver<Message> messageReceiver;
	//private Receiver<Integer> integerReceiver;

	private Sender<Head> headSender;
	//private Sender<Integer> integerSender;
	//private Sender<Message> messageSender;
	//private Sender<HashMap<Integer,Player>> playerListSender;
	//private Sender<Player> playerSender;
	
	//Heads
	private Head headGameStart = new HeadGameStarting();
	private Head headGameOver = new HeadGameOver();
	private Head headPlayerList = new HeadPlayerList();
	private Head headResult = new HeadResult();
	private Head headMessage = new HeadMessage();
	private Head headReadyNotification = new HeadReadyNotification();
	private Head headRoundDone = new HeadRoundDone();
	private Head headPlayer = new HeadPlayer();
	
	private ArrayList<ClientObserver > observers = new ArrayList<ClientObserver>();	
	private Player player;
	private Integer id;
	
	
	public ClientHandler(Socket socket,Integer id){
		this.id = id;
		this.socket = socket;
		try {
                    output = new ObjectOutputStream(socket.getOutputStream());    
                    InputStream in = socket.getInputStream();
                        
			input = new ObjectInputStream(in);
			
			
			headReceiver = new Receiver<Head>(input);
			//playerReceiver = new Receiver<Player>(input);
			//messageReceiver = new Receiver<Message>(input);
			//integerReceiver = new Receiver<Integer>(input);
			
			headSender = new Sender<Head>(output);
			//integerSender = new Sender<Integer>(output);
			//messageSender = new Sender<Message>(output);
			//playerListSender = new Sender<HashMap<Integer,Player>>(output);
			//playerSender = new Sender<Player>(output);
			
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	@Override
	protected void task() {
		try{
		Head head = headReceiver.receive();
		int option = head.getObjectId();
		
		switch(option){
		case HeadsConst.PLAYER :  playerDelivery((Player)head.getObject());break;
		case HeadsConst.ROUND_DONE: roundDoneDelivery();break;
		case HeadsConst.READY: playerIsReadyDelivery();break;
		case HeadsConst.MESSAGE: messageDelivery((Message)head.getObject());break;
		
		}
		
		}catch(Exception e){
			
		}
	}
	
	private void playerDelivery(Player player) throws IOException, ClassNotFoundException{
		this.player = player;
		
		
		Credit credit = new Credit();
		credit.setValue(1000);
		player.setId(id);
		player.setCredits(credit);
                headPlayer.setObject(player);
		headSender.setObject(headPlayer);
                //playerSender.setObject(player);
		
		try{
                        
			headSender.send();
                        //Thread.sleep(100);
                        //playerSender.send();
			
		}catch(Exception e){
			
		}
                for(ClientObserver ob:observers){
			ob.updatePlayer(player,id);
		}
	}
	private void roundDoneDelivery(){
		for(ClientObserver ob:observers){
			ob.updateRoundDone(id);
		}
	}
	private void playerIsReadyDelivery(){
		for(ClientObserver ob:observers){
			ob.updateReady(id);
		}
	}
	private void messageDelivery(Message msg) throws IOException, ClassNotFoundException{
		
		for(ClientObserver ob:observers){
			ob.updateMessage(msg);
		}
	}
	
	public void sendPlayerlist(HashMap<Integer,Player> playerList ){
            headPlayerList.setObject(playerList);
            headSender.setObject(headPlayerList);
		//playerListSender.setObject(playerList);
		try {
			headSender.send();
			//playerListSender.send();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	public void sendGameIsStarting(){
                headGameStart.setObject(true);
		headSender.setObject(headGameStart);
		try {
			headSender.send();
		} catch (IOException e) {
		
			e.printStackTrace();
		}
	}
	public void sendGameIsEnding(){
                headGameOver.setObject(true);
		headSender.setObject(headGameOver);
		try {
			headSender.send();
		} catch (IOException e) {
			
			e.printStackTrace();
		}
	}
	public void sendResult(Integer result){
            headResult.setObject(result);
            headSender.setObject(headResult);
		//integerSender.setObject(result);
		
		try {
			headSender.send();
			//integerSender.send();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	public void sendReadyNotification(Integer playerId){
            headReadyNotification.setObject(playerId);
            headSender.setObject(headReadyNotification);
		//integerSender.setObject(playerId);
		try {
			
			headSender.send();
			//integerSender.send();
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	public void sendMessage(Message msg){
                headMessage.setObject(msg);
		headSender.setObject(headMessage);
                
		//messageSender.setObject(msg);
		
		try {
			headSender.send();
			//messageSender.send();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public void sendRoundDoneNotification(Integer playerId){
            headRoundDone.setObject(playerId);
            headSender.setObject(headRoundDone);
		//integerSender.setObject(playerId);
		try {
			headSender.send();
			//integerSender.send();
		} catch (IOException e) {
		
			e.printStackTrace();
		}
	}
	
	@Override
	public void registerObserver(ClientObserver observer) {
		observers.add(observer);
	}

	@Override
	public void removeObserver(ClientObserver observer) {
		observers.remove(observer);
	}

	@Override
	public void notifyObservers() {
	
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

}
